package com.rhb.ca.web.filter;

import com.rhb.ca.web.util.CaUrl;
import com.rhb.ca.web.util.ConfigPage;
import com.rhb.ca.web.util.Constant;
import com.rhb.ca.web.util.HttpConnect;
import com.rhb.ca.web.util.ProtectedResource;
import com.rhb.ca.role.bean.Role;
import com.rhb.ca.web.util.SignOnDAO;
import com.rhb.ca.uzer.bean.Uzer;
import com.rhb.ca.uzer.business.UzerBusiness;
import com.rhb.ca.AppContext;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;


public class SignOnFilter implements Filter{

    private HashMap protectedResources;
    private FilterConfig config;
    private ConfigPage configPage;
    private String caservice;
    private String appRoot;

    public SignOnFilter(){
        config = null;
        caservice = null;
        appRoot = null;
    }

    public void init(FilterConfig config) throws ServletException{
        this.config = config;
        caservice = config.getInitParameter("caservice");
        String resurl = config.getInitParameter("resource");
        
        configPage = new ConfigPage();
        configPage.setCaService(caservice);
        if(resurl!=null&&!"".equals(resurl)) configPage.setResourceUrl(resurl);
        
        java.net.URL protectedResourcesURL = null;
        try{
            configPage.appRoot = config.getServletContext().getServletContextName();
            configPage.loginRoles = config.getServletContext().getInitParameter("roles");
            configPage.loginaction = Constant.LOGIN_FORM_ACTION;
            
            protectedResourcesURL = config.getServletContext().getResource("/WEB-INF/signon-config.xml");
            if(protectedResourcesURL != null){
                SignOnDAO dao = new SignOnDAO(protectedResourcesURL);
                configPage.setSignOnPage(dao.getSignOnPage());
                configPage.setSignOutPage(dao.getSignOutPage());
                configPage.setSignOnSuccessPage(dao.getSignOnSuccessPage());
                configPage.setSignOnErrorPage(dao.getSignOnErrorPage());
                configPage.setForbiddenPage(dao.getForbiddenPage());
                protectedResources = dao.getProtectedResources();
            }
        }
        catch(MalformedURLException ex)
        {
        	ex.printStackTrace();
        }
    }

    public void destroy()
    {
        config = null;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException
    {
    	request.setAttribute("caservice",caservice);
        HttpServletRequest hreq = (HttpServletRequest)request;
        HttpServletResponse hres = (HttpServletResponse)response;
        
        String targetURL = null;
        String currentURL = hreq.getRequestURI();
        appRoot = hreq.getContextPath() + "/";

        int firstSlash = currentURL.indexOf(appRoot, 0);
        if(firstSlash != -1)
        	targetURL = currentURL.substring(firstSlash + appRoot.length(), currentURL.length());

        if(targetURL == null||"".equals(targetURL.trim())){
            chain.doFilter(request, response);
            return;
        }
        if(targetURL.equals(Constant.LOGIN_FORM_ACTION)){
            validateSignOn(request, response, chain);
            return;
        }
        if(targetURL.equals(Constant.DO_LOGOUT)){
            validateSignOut(request, response, chain);
            return;
        }
        if(targetURL.equals(Constant.DO_LOGIN)){
            configPage.sendRedirect(hreq, hres, Constant.CAS_PAGE_LOGIN);
            return;
        }
        boolean iscpage = configPage.pageBuild(hreq, hres, chain, targetURL);
        if(!iscpage){
            if(targetURL.indexOf(".jsp") > 0 || targetURL.indexOf(".asp") > 0 
            	|| targetURL.indexOf(".do") > 0 || targetURL.indexOf(".jsf") > 0 
            	|| targetURL.indexOf(".php") > 0 || targetURL.indexOf(".htm") > 0 
            	|| targetURL.indexOf(".xml") > 0 || targetURL.indexOf(".screen") > 0 
            	|| targetURL.indexOf(".html") > 0 || targetURL.indexOf(".shtml") > 0){
            	
            	hreq.getSession(true).setAttribute(Constant.USABLE_URL,HttpConnect.getCurrentUrl(hreq));

                boolean isProtected = false;
                Iterator pit = null;
                if(protectedResources != null)
                    pit = protectedResources.keySet().iterator();
                while(pit != null && pit.hasNext()){
                    String protectedName = (String)pit.next();
                    ProtectedResource resource = (ProtectedResource)protectedResources.get(protectedName);
                    if(resource.existURL(targetURL)){
                        isProtected = true;
                        break;
                    }
                }
                if(!isProtected){
                    chain.doFilter(request, response);
                    return;
                }
                Uzer uzer = getLoginUzer(hreq);
                if(uzer != null){
                    ArrayList roles_targetURL = new ArrayList();
                    Iterator it = null;
                    if(protectedResources != null)
                        it = protectedResources.keySet().iterator();
                    while(it != null && it.hasNext()){
                        String protectedName = (String)it.next();
                        ProtectedResource resource = (ProtectedResource)protectedResources.get(protectedName);
                        if(resource.existURL(targetURL))
                            roles_targetURL.addAll(resource.getRoles());
                    }
                    
                    boolean forbidden = true;
                    Set roles_uzer = uzer.getRoles();
                    Role rol = null;
                    if(roles_targetURL == null || roles_targetURL.size() < 1)
                        forbidden = false;
                    else if("*".equals((String)roles_targetURL.get(0))){
                        forbidden = false;
                    }else{
                    	if(roles_uzer != null){
                    		Iterator iterator = roles_uzer.iterator();
                    		while(iterator.hasNext()){
                    			rol = (Role)iterator.next();
                                for(int j = 0; j < roles_targetURL.size(); j++){
                                    if(!rol.getRoleName().toLowerCase().equals(((String)roles_targetURL.get(j)).toLowerCase()))
                                        continue;
                                    forbidden = false;
                                    break;
                                }

                                if(!forbidden) break;
                            }                    		
                    	}

                    }
                    if(forbidden){
                        configPage.sendRedirect(hreq, hres,Constant.CAS_PAGE_FORBID);
                        return;
                    }else{
                        chain.doFilter(request, response);
                        return;
                    }
                }else{
                    configPage.sendRedirect(hreq, hres, Constant.CAS_PAGE_LOGIN);
                    return;
                }
            }
            chain.doFilter(request, response);
        }
        return;
    }

    public Uzer getLoginUzer(HttpServletRequest request) throws IOException, ServletException{
    	Uzer uzer = null;
    	try{
    		uzer = HttpConnect.getUzerFromCurrentServer(request);
    	}catch(Exception e){}
    	if(uzer!=null) return uzer;
    	
        if(caservice == null || "".equals(caservice.trim())) return null;
        String usableurl = (String)request.getSession(true).getAttribute(Constant.USABLE_URL);
        
        HttpConnect hc = new HttpConnect(caservice);
        hc.add(Constant.CAS_ACTION, Constant.CAS_GETUZER);
        hc.add(Constant.SESSIONID, request.getSession(true).getId());
        hc.add(Constant.TOUCH_IP, request.getRemoteHost());
        if(usableurl != null) hc.add(Constant.TOUCH_URL, usableurl);
        return (Uzer)hc.connect();
    }

    public void validateSignOn(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException{
        HttpServletRequest hreq = (HttpServletRequest)request;
        HttpServletResponse hres = (HttpServletResponse)response;
        
        String loginName = CaUrl.valueOf(hreq,Constant.LOGIN_FIELD_UZER);
        String password = CaUrl.valueOf(hreq,Constant.LOGIN_FIELD_PASS);
        Uzer uzer = null;
        String usableurl = (String)hreq.getSession(true).getAttribute(Constant.USABLE_URL);
        if(caservice == null || "".equals(caservice.trim())){
            try{
            	UzerBusiness ub = (UzerBusiness)AppContext.getInstance().getAppContext().getBean("uzerService");
            	uzer = ub.selectUzerByLoginName(loginName);
            }catch(Exception ex){
                ex.printStackTrace();
                uzer = null;
            }
        }else{
            HttpConnect hc = new HttpConnect(caservice);
            hc.add(Constant.CAS_ACTION, "login");
            hc.add(Constant.LOGIN_FIELD_UZER, loginName);
            hc.add(Constant.LOGIN_FIELD_PASS, password);
            hc.add(Constant.SESSIONID, hreq.getSession(true).getId());
            hc.add(Constant.TOUCH_IP, hreq.getRemoteHost());
            if(usableurl != null)
                hc.add(Constant.TOUCH_URL, usableurl);
            try{
                uzer = (Uzer)hc.connect();
            }catch(Exception ex) { }
        }
        if(uzer == null){
            configPage.sendRedirect(hreq, hres, Constant.CAS_PAGE_LOGIN);
        } else{
            if(usableurl == null)
                configPage.sendRedirect(hreq, hres,Constant.CAS_PAGE_SUCCESS);
            else
                hres.sendRedirect(usableurl);
        }
    }

    public void validateSignOut(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException
    {
        HttpServletRequest hreq = (HttpServletRequest)request;
        HttpServletResponse hres = (HttpServletResponse)response;
        String usableurl = (String)hreq.getSession(true).getAttribute(Constant.USABLE_URL);
        if(caservice != null && !"".equals(caservice.trim())){
            HttpConnect hc = new HttpConnect(caservice);
            hc.add(Constant.CAS_ACTION, Constant.CAS_DOLOGOUT);
            hc.add(Constant.SESSIONID, hreq.getSession(true).getId());
            hc.add(Constant.TOUCH_IP, hreq.getRemoteHost());
            if(usableurl != null)
                hc.add(Constant.TOUCH_URL, usableurl);
            hc.connect();
        }
        hreq.getSession().removeAttribute(Constant.CAS_UZER_KEY);
        hreq.getSession().removeAttribute(Constant.SIGNED_ON_UZER);
        configPage.sendRedirect(hreq, hres, Constant.CAS_PAGE_LOGOUT);
    }
}
